package com.personal.system.config;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.personal.common.utils.JwtHelper;
import com.personal.model.system.SysUser;
import com.personal.system.exception.GlobalException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Collection;

@Component("securityUtil")
public class SecurityUtil {

    private Logger logger = LoggerFactory.getLogger(SecurityUtil.class);

    @Resource
    private UserDetailsService userDetailsService;
    @Resource
    private RedisTemplate redisTemplate;

    public String getUserName() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (null != authentication){
            String userName = (String) authentication.getPrincipal();

            return userName;
        }
        return "";
    }

    public Long getUserId() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (null != authentication){
            SysUser sysUser = JSONObject.parseObject( authentication.getCredentials().toString(), SysUser.class);
            return Long.valueOf(sysUser.getId());
        }
        return Long.valueOf(checkLogin());
    }

    public SysUser getUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (null != authentication){
            SysUser sysUser = JSONObject.parseObject( authentication.getCredentials().toString(), SysUser.class);
            return sysUser;
        }
        return null;
    }

    public String checkLogin() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader("token");
        if (StrUtil.isBlank(token)) throw new GlobalException(401, "未登陆不能操作!");
        String userId = JwtHelper.getUser(token).get("userId").toString();
        String username = JwtHelper.getUser(token).get("username").toString();
        String key =  "login_user_key:" + username;
        ValueOperations operations = redisTemplate.opsForValue();
        Object obj = operations.get(key);
        if (obj == null)  throw new GlobalException(401, "未登陆不能操作!");
        else return userId;
    }

    public String getUserIdWeb() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader("token");
        if (StrUtil.isBlank(token)) return null;
        String userId = JwtHelper.getUser(token).get("userId").toString();
        return userId;
    }

    public void logInAs(String username) {

        UserDetails user = userDetailsService.loadUserByUsername(username);
        if (user == null) {
            throw new IllegalStateException("User " + username + " doesn't exist, please provide a valid user");
        }
        logger.info("> Logged in as: " + username);
        SecurityContextHolder.setContext(new SecurityContextImpl(new Authentication() {
            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                return user.getAuthorities();
            }

            @Override
            public Object getCredentials() {
                return user.getPassword();
            }

            @Override
            public Object getDetails() {
                return user;
            }

            @Override
            public Object getPrincipal() {
                return user;
            }

            @Override
            public boolean isAuthenticated() {
                return true;
            }

            @Override
            public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {

            }

            @Override
            public String getName() {
                return user.getUsername();
            }
        }));
//        org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);
    }
}
